package com.patterns.singleton;

import java.util.concurrent.CountDownLatch;

/**
 * 使用CountDownLatch线程计数器辅助测试五种单例模式并发效率
 * 测试10线程，每线程访问100万次单例
 * 测试结果:
 * 饿汉式单例模式:10
 * 懒汉式单例模式:153
 * 双重检测锁式单例模式:7
 * 静态内部类单例模式:70
 * 枚举单例模式:6
 * @author huangke
 *
 */
public class CountDownLatchSingleton {
	
	public static void main(String[] args) throws Exception{
		System.out.println("饿汉式单例模式:" + checkSingletonDemo1());
		System.out.println("懒汉式单例模式:" + checkSingletonDemo2());
		System.out.println("双重检测锁式单例模式:" + checkSingletonDemo3());
		System.out.println("静态内部类单例模式:" + checkSingletonDemo4());
		System.out.println("枚举单例模式:" + checkSingletonDemo5());
	}
	
	public static long checkSingletonDemo1() throws Exception{
		long start = System.currentTimeMillis();
		int threadNum = 10;
		
		final CountDownLatch latch = new CountDownLatch(threadNum);
		for (int i = 0; i < threadNum; i++) {
			new Thread(new Runnable() {
				
				public void run() {
					for (int j = 0;j < 1000000; j++) {
						SingletonDemo1 demo = SingletonDemo1.getInstance();
					}
					latch.countDown(); // >> 执行完一次线程计数器减1
				}
			}).start();
		}
		
		latch.await();// >> 阻塞主线程，直到计数器归0
		
		long end = System.currentTimeMillis();
		
		return end - start;
	}
	
	public static long checkSingletonDemo2() throws Exception{
		long start = System.currentTimeMillis();
		int threadNum = 10;
		
		final CountDownLatch latch = new CountDownLatch(threadNum);
		for (int i = 0; i < threadNum; i++) {
			new Thread(new Runnable() {
				
				public void run() {
					for (int j = 0;j < 1000000; j++) {
						SingletonDemo2 demo = SingletonDemo2.getInstance();
					}
					latch.countDown(); // >> 执行完一次线程计数器减1
				}
			}).start();
		}
		
		latch.await();// >> 阻塞主线程，直到计数器归0
		
		long end = System.currentTimeMillis();
		
		return end - start;
	}
	
	public static long checkSingletonDemo3() throws Exception{
		long start = System.currentTimeMillis();
		int threadNum = 10;
		
		final CountDownLatch latch = new CountDownLatch(threadNum);
		for (int i = 0; i < threadNum; i++) {
			new Thread(new Runnable() {
				
				public void run() {
					for (int j = 0;j < 1000000; j++) {
						SingletonDemo3 demo = SingletonDemo3.getInstance();
					}
					latch.countDown(); // >> 执行完一次线程计数器减1
				}
			}).start();
		}
		
		latch.await();// >> 阻塞主线程，直到计数器归0
		
		long end = System.currentTimeMillis();
		
		return end - start;
	}
	
	public static long checkSingletonDemo4() throws Exception{
		long start = System.currentTimeMillis();
		int threadNum = 10;
		
		final CountDownLatch latch = new CountDownLatch(threadNum);
		for (int i = 0; i < threadNum; i++) {
			new Thread(new Runnable() {
				
				public void run() {
					for (int j = 0;j < 1000000; j++) {
						SingletonDemo4 demo = SingletonDemo4.getInstance();
					}
					latch.countDown(); // >> 执行完一次线程计数器减1
				}
			}).start();
		}
		
		latch.await();// >> 阻塞主线程，直到计数器归0
		
		long end = System.currentTimeMillis();
		
		return end - start;
	}
	
	public static long checkSingletonDemo5() throws Exception{
		long start = System.currentTimeMillis();
		int threadNum = 10;
		
		final CountDownLatch latch = new CountDownLatch(threadNum);
		for (int i = 0; i < threadNum; i++) {
			new Thread(new Runnable() {
				
				public void run() {
					for (int j = 0;j < 1000000; j++) {
						SingletonDemo5 demo = SingletonDemo5.INSTANCE;
					}
					latch.countDown(); // >> 执行完一次线程计数器减1
				}
			}).start();
		}
		
		latch.await();// >> 阻塞主线程，直到计数器归0
		
		long end = System.currentTimeMillis();
		
		return end - start;
	}
}
